package com.apes.scm.contract.service;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.apes.framework.api.DomainService;
import com.apes.framework.api.SpringManager;
import com.apes.framework.jpa.logger.ApesLoggerService;
import com.apes.framework.jpa.spec.JpaDsl;
import com.apes.framework.jpa.spec.model.Group;
import com.apes.framework.plugin.esb.api.SimpleRequest;
import com.apes.framework.plugin.event.Listener;
import com.apes.framework.plugin.mq.MQUtil;
import com.apes.framework.plugin.mq.annotation.Consumer;
import com.apes.framework.plugin.outbox.OutboxPayloadWrapper;
import com.apes.framework.plugin.outbox.OutboxSubscriberService;
import com.apes.framework.plugin.outbox.annotation.OutboxSubscriber;
import com.apes.framework.plugin.soe.metadata.BusinessAttributeValue;
import com.apes.framework.plugin.soe.store.database.repository.BusinessAttributeValueRepository;
import com.apes.framework.util.DateUtil;
import com.apes.framework.util.MapUtil;
import com.apes.pi.service.PiManager;
import com.apes.scm.account.account.model.Cooperation;
import com.apes.scm.account.account.repository.CooperationRepository;
import com.apes.scm.contract.model.Contract;
import com.apes.scm.contract.repository.ContractRepository;
import com.apes.scm.masterdata.contrast.model.ContrastPartyCode;
import com.apes.scm.masterdata.contrast.repository.ContrastPartyCodeRepository;
import com.apes.scm.masterdata.enumeration.repository.EnumerationRepository;
import com.apes.scm.masterdata.frame.model.Dept;
import com.apes.scm.masterdata.frame.repository.DeptRepository;
import com.apes.scm.masterdata.party.model.PartyRole;
import com.apes.scm.masterdata.party.repository.PartyRoleRepository;
import com.apes.scm.voucher.service.VoucherType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.*;
import org.springframework.stereotype.Service;

import javax.xml.crypto.Data;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 功能：合同服务
 *
 * @author xul
 * @create 2018-04-12 16:40
 */
@Service("contractService")
public class ContractService extends DomainService {

    @Autowired
    private ContractRepository contractRepository;
    @Autowired
    private PiManager piManager;
    @Autowired
    private PartyRoleRepository partyRoleRepository;
    @Autowired
    private ContrastPartyCodeRepository contrastPartyCodeRepository;
    @Autowired
    private ApesLoggerService apesLoggerService;

    @Value("${apes.switched:false}")
    private Boolean switched;


    /**
     * 新增
     * 1. 同一有效期内，同供应商、采购部门、合作方式只能有一份有效合同
     * 2. 同一供应商、采购部门、合作方式的两份合同时间段不能重复
     *
     * @param request
     * @return
     * 检查
     */
    public Contract save(SimpleRequest request) throws Exception {
        Contract contract = request.getO(Contract.class);
        List<Contract> contracts = contractRepository.findAll(
                JpaDsl.toCriteria("partner.id", "eq", contract.getPartner().getId(), "contractType.id", "eq", contract.getContractType().getId(),
                        "state", "in", Arrays.asList("create", "approve", "extension"), "contractType.id", "NE", "Contract.contractType.customer")

        );
        if (!contracts.isEmpty()) throw new RuntimeException("同一个供应商不能签署两份合同，请先终止，合同编码：" + contracts.get(0).getId());

        checkDate(contract, true);
        //自编ID规则(销售合同除外)
        if (!contract.getContractType().getId().contains("customer")) contract.setId(ruleForId(contract));
        checkCompany(contract);
        contract.setState("create");
        contract.setCreator(request.getPersonId());
        return contractRepository.saveAndFlush(contract);
    }

    /**
     * 不检查
     * @param request
     * @return
     * @throws Exception
     */
    public Contract saveNew(SimpleRequest request) throws Exception {
        Contract contract = request.getO(Contract.class);
        checkDate(contract, false);
        //自编ID规则(销售合同除外)
        if (!contract.getContractType().getId().contains("customer")) contract.setId(ruleForId(contract));
        checkCompany(contract);
        contract.setState("create");
        contract.setCreator(request.getPersonId());
        return contractRepository.saveAndFlush(contract);
    }

    /**
     * 手动生成合同id
     * 前缀（2）+ 公司id（4） + 年月（4） + 流水码（3）
     * @param contract
     * @return
     */
    public String ruleForId(Contract contract) {
        StringBuffer id = new StringBuffer();
        if (contract.getContractType().getId().contains("supplier")) id.append("HT");
        if (contract.getContractType().getId().contains("platform")) id.append("XY");
        //公司
        id.append(contract.getCompany().getId());
        //时间
        SimpleDateFormat sdf = new SimpleDateFormat("yyMM");
        id.append(sdf.format(new Date()));
        //根据类型找最新一条数据
        List<Contract> contractList = contractRepository.findMaxId(contract.getContractType().getId().contains("supplier")?"HT":"XY");
        Contract newContract = contractList.stream().max(Comparator.comparing(e->e.getId().substring(e.getId().length()-3))).get();
        if (newContract != null) {
            String sub = newContract.getId().substring(newContract.getId().length()-3);
            sub = Integer.valueOf(sub) + 1 + "";
            if (sub.length()< 4) {
                while (sub.length() < 3) {
                    sub = "0" + sub;
                }
                id.append(sub);
            }else {
                id.append("001");
            }
        }else {
            id.append("001");
        }
        return id.toString();
    }


    public JSONObject findSupplierDetailed(SimpleRequest request){
        JSONObject jo = request.getJO();
        JSONObject node = jo.getJSONObject("node");
        JSONObject contract = node.getJSONObject("contract");
        if (contract==null)return new JSONObject();
        String id = contract.getString("id");
        Contract contractPojo = contractRepository.findOne(id);
        JSONObject resultJson = new JSONObject(MapUtil.mapper(
                "supplier",'['+contractPojo.getPartner().getId()+']'+contractPojo.getPartner().getName(),
                "isInvoicing",contractPojo.getCompany().getParty().getCorporate().isWantInvoice()?"开票":"不开票",
                "contract",'['+contractPojo.getId()+']'+contractPojo.getName(),
                "cooperationType",contractPojo.getCooperation().getName(),
                "platform",node.getJSONObject("platform").getString("id")
        ));
        return resultJson;
    }
    /**
     * 检查数据是否已经被修改
     *
     * @param request
     */
    public void check(SimpleRequest request) {
        Contract contract = contractRepository.findOne((String) request.get("id"));
        if (contract == null) throw new RuntimeException("合同" + request.get("id") + "在系统中不存在");
        if (contract.getVersion() != (int) request.get("version"))
            throw new RuntimeException("合同" + request.get("id") + "记录已更新或已删除");
    }

    /**
     * 修改
     *
     * @param request
     * @return
     */
    public Contract update(SimpleRequest request) throws Exception {
        Contract contract = request.getO(Contract.class);
        checkCompany(contract);
        contract.setState("create");

        check(request);
        checkDate(contract, true);
        return contractRepository.saveAndFlush(contract);
    }

    /**
     * 审核
     *
     * @param request
     * @return
     */
    public Contract approve(SimpleRequest request) throws Exception {
        check(request);
        Contract contract = request.getO(Contract.class);
        checkCompany(contract);
        checkDate(contract,true);
//        if (contract.getCarryType() != null) {
//            if ("自提".equals(contract.getCarryType().getName())) {
//                List<SupplierShip> list = SpringManager.getBean(SupplierShipRepository.class).findAll(
//                        JpaDsl.toCriteriaByEq("supplier",contract.getPartner())
//                );
//                if (list.size() == 0) throw new RuntimeException("提货方式为自提的,要求供应商维护发货地点!!!");
//            } else if ("送货".equals(contract.getCarryType().getName())) {
//                List<SupplierReach> list = SpringManager.getBean(SupplierReachRepository.class).findAll(
//                        JpaDsl.toCriteriaByEq("supplier",contract.getPartner())
//                );
//                if (list.size() == 0) throw new RuntimeException("提货方式为送货的,要求供应商维护可送达仓库!!!");
//            }
//        }
        contract.setState("approve");
        contract.setApproveDate(new Date());
        contract.setApproveUid(this.getPerson(request));

        // 需将数据同步到老框架
        if (!"Contract.contractType.customer".equals(contract.getContractType().getId())){
            JSONObject returnCGHT = this.formatCGHT(contract);
            returnCGHT.put("CZY", contract.getCreator());
            SpringManager.getBean(OutboxSubscriberService.class).commonSendRequest("local:contractService.synOldCGHT", "contract:" + contract.getId(), returnCGHT);
        }
        return contractRepository.saveAndFlush(contract);
    }

    @OutboxSubscriber(id = "local:contractService.synOldCGHT", name = "平台协议同步到老框架")
    public void synOldCGHT(OutboxPayloadWrapper outboxPayloadWrapper) {
        piManager.synErp("scmCghtService.insert", outboxPayloadWrapper.getPayload());
    }

    /**
     * 终止
     *
     * @param request
     * @return
     */
    public Contract repeal(SimpleRequest request) {
        Contract contract = request.getO(Contract.class);
        contract.setState("repeal");
        contract.setRepealDate(new Date());
        if (contract.getRepealUid() == null) contract.setRepealUid(this.getPerson(request));
        if (!"Contract.contractType.customer".equals(contract.getContractType().getId())) {
            JSONObject returnCGHT = this.formatCGHT(contract);
            returnCGHT.put("CZY", contract.getRepealUid().getName());
            piManager.synErp("scmCghtService.exec_Submit", returnCGHT);
        }
        return contractRepository.saveAndFlush(contract);
    }

    /**
     * 旧框架终止采购合同
     * @param request
     */
    public void oldFrameRepeal(SimpleRequest request) throws ParseException {
        JSONObject getJO = request.getJO();
        List<Contract> contractList = contractRepository.findAll(JpaDsl.toCriteriaByEq("id", getJO.get("CGHTH")));
        if (contractList.size() > 0) {
            Contract contract = contractList.get(0);
            contract.setState("repeal");
            contract.setRepealDate(new Date());
            contract.setRepealUid(this.getPerson(request));
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
            Date date = simpleDateFormat.parse(getJO.getString("YXQZ"));
            contract.setValidPeriod(date);
            contractRepository.save(contract);
        }
    }

    /**
     * 延期
     *
     * @param request
     * @return
     */
    public Contract extension(SimpleRequest request) throws Exception {
        Contract contract = request.getO(Contract.class);
        contract.setState("extension");

        checkDate(contract, true);
        contract.setExtensionUid(this.getPerson(request));
        contract.setExtensionDate(new Date());

        if (!"Contract.contractType.customer".equals(contract.getContractType().getId())) {
            JSONObject returnCGHT = this.formatCGHT(contract);
            returnCGHT.put("CZY", contract.getExtensionUid().getName());
            piManager.synErp("scmCghtService.exec_Submit", returnCGHT);
        }
        return contractRepository.saveAndFlush(contract);
    }

    /**
     * 老框架延期
     * @param request
     */
    public void oldFrameExtension(SimpleRequest request) {
        JSONObject getJO = request.getJO();
        List<Contract> contractList = contractRepository.findAll(JpaDsl.toCriteriaByEq("originId", getJO.get("CGHTH")));
        if (contractList.size() > 0) {
            Contract contract = contractList.get(0);
            contract.setState("extension");
            contract.setValidPeriod(getJO.getDate("YXQZ"));
            contractRepository.save(contract);
        }
    }

    /**
     * 删除
     *
     * @param request
     * @return
     */
    public String delete(SimpleRequest request) {
        check(request);
        Contract contract = request.getO(Contract.class);
        contract.setState("delete");
        contract.setDeleteDate(new Date());
        contract.setDeleteUid(getPerson(request));
        contractRepository.save(contract);
        return "删除成功";
    }

    /**
     * 检查数据
     * @param contract
     */
    public void checkCompany(Contract contract){
        if (!contract.getCompany().getId().equals(contract.getDept().getCompany().getId())) throw new RuntimeException("该公司和部门不匹配！");
    }
    /**
     * 检查时间
     *
     * @param contract
     * @throws Exception
     */
    public void checkDate(Contract contract, boolean checkOldContract) throws Exception {
        DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd");

        Date parseValidFrom = dateFormat.parse(dateFormat.format(contract.getValidFrom()));     // 开始
        Date parseValidPeriod = dateFormat.parse(dateFormat.format(contract.getValidPeriod())); // 结束

        long validFromTime = parseValidFrom.getTime();
        long validEndTime = parseValidPeriod.getTime();
        if (validEndTime < validFromTime) throw new RuntimeException("有效期止不能小于有效期起");

        Date currentDate = dateFormat.parse(dateFormat.format(new Date()));  // 当前时间
        long currentDateTime = currentDate.getTime();
        if (validEndTime < currentDateTime) throw new RuntimeException("有效期止不能小于当前日期");

        // 检查合同
        if (checkOldContract) {
            checkOldContract(contract);
        }
    }

    /**
     * 同一有效期内同一供应商、公司下有效期合同只能有一份
     *
     * @param contract
     */
    public void checkOldContract(Contract contract) throws Exception {
        DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd");
        List<Map> condition = new ArrayList<>();

        List<Contract> oldContract = contractRepository.findByCompanyAndPartner(contract.getCompany().getId(), contract.getPartner().getId(), contract.getContractType().getId());
        oldContract = oldContract.stream().filter(e-> !e.getId().equals(contract.getId())).collect(Collectors.toList());
        for (Contract con : oldContract) {
            Date oldFromDate = dateFormat.parse(dateFormat.format(con.getValidFrom()));
            long oldFromDateTime = oldFromDate.getTime();       // 开始

            Date oldEndDate = dateFormat.parse(dateFormat.format(con.getValidPeriod()));
            long oldEndDateTime = oldEndDate.getTime();     // 结束

            Date date = new Date();
            long newDate = date.getTime();//当前时间

            if (newDate >= oldFromDateTime && newDate <= oldEndDateTime) {
                String str = con.getContractType().getId().contains("supplier")?"合同":"协议";
                throw new RuntimeException("已存在有效"+ str +"："+ con.getId() +"！");
            }
        }
    }

    /**
     * 格式化采购合同
     * @param contract
     * @return
     */
    private JSONObject formatCGHT(Contract contract) {
        JSONObject returnCGHT = new JSONObject();
        returnCGHT.put("CGHTH", contract.getId());
        returnCGHT.put("GYSMC", contract.getPartner().getName());
        returnCGHT.put("YXQQRQ_SJ", DateUtil.format(contract.getValidFrom(), "yyyy/MM/dd"));
        returnCGHT.put("YXQZRQ_SJ", DateUtil.format(contract.getValidPeriod(), "yyyy/MM/dd"));
        if (!"Contract.contractType.customer".equals(contract.getContractType().getId())){
            String settlementType = contract.getSettlementType().getCode();
            switch (settlementType) {
                case "month":
                    returnCGHT.put("JSZQ", 3);
                    break;
                case "halfMonth":
                    returnCGHT.put("JSZQ", 2);
                    break;
                case "week":
                    returnCGHT.put("JSZQ", 1);
                    break;
                case "bill":
                    returnCGHT.put("JSZQ", 0);
                    break;
                case "totalCash":
                    returnCGHT.put("JSZQ", 4);
                    break;
                case "deptCash":
                    returnCGHT.put("JSZQ", 5);
                    break;
            }
        }
        String cooperation = contract.getCooperation().getId();
        if ("distribution".equals(cooperation)) {
            if (contract.isConsignInstall()){
                returnCGHT.put("HZFS", 3);
            }else {
                returnCGHT.put("HZFS", 0);
            }
        } else if ("consignment".equals(cooperation)) {
            if (contract.isConsignInstall()){
                returnCGHT.put("HZFS", 2);
            }else {
                returnCGHT.put("HZFS", 1);

            }
        }


        if (contract.getCarryType() == null || "Contract.carryType.delivery".equals(contract.getCarryType().getId())) {
            returnCGHT.put("JHFSID","60");
            returnCGHT.put("JHFSMC", "送货上门");
        }else {
            returnCGHT.put("JHFSID", "10");
            returnCGHT.put("JHFSMC", "自取");
        }
        returnCGHT.put("KPFS", 0);
        returnCGHT.put("ZQTS", 0);
        returnCGHT.put("ZDR", contract.getCreator());
        returnCGHT.put("GSID", contract.getCompany().getId());
        returnCGHT.put("C_CDNM", "makeCGHT");
        returnCGHT.put("DJLXID", "CH0");
        returnCGHT.put("XKJDHBJ", 1);

        String state = contract.getState();
        if ("approve".equals(state)) {
            returnCGHT.put("DJZT", 0);
        } else if ("repeal".equals(state)) {
            returnCGHT.put("DJZT", 30);
        }  else if ("extension".equals(state)) {
            returnCGHT.put("DJZT", 20);
        }
        if (contract.getApproveUid() != null) {
            returnCGHT.put("SHR", contract.getApproveUid().getName());
        } else if (contract.getRepealUid() != null) {
            returnCGHT.put("ZZR", contract.getRepealUid().getName());
        } else if (contract.getExtensionUid() != null) {
            returnCGHT.put("YQR", contract.getExtensionUid().getName());
        }
        returnCGHT.put("CGHTMC", contract.getName());
        if (contract.getContractType().getCode().indexOf("platform") != -1) {
            returnCGHT.put("CGHTLX", 2);
        } else {
            returnCGHT.put("CGHTLX", 0);
        }


        PartyRole partyRole = partyRoleRepository.findOne(contract.getPartner().getId());
        List<ContrastPartyCode> contrastPartyCodeList = contrastPartyCodeRepository.findAll(JpaDsl.toCriteriaByEq("party.id", partyRole.getParty().getId()));
        if (contrastPartyCodeList.size() == 0) {
            throw new RuntimeException("请配置角色对照表");
        }
        returnCGHT.put("GYSID", contrastPartyCodeList.get(0).getGysid());

        JSONObject responseData = piManager.synErp("masterDataConversionService.queryCGZZ", returnCGHT);
        responseData = JSONObject.parseObject(responseData.get("obj").toString());
        returnCGHT.putAll(responseData);
        return returnCGHT;
    }

    /**
     * 下拉查询使用
     * @param request
     * @return
     * @throws Exception
     */
    public Page<Contract> find(SimpleRequest request) throws Exception {
        return contractRepository.find(request.get("key"), PageRequest.of(request.get("page"), request.get("size")));
    }

    /**
     * 查找合同（外协派工根据平台查找）
     * @param simpleRequest
     * @return
     */
    public Page<Map> findAllBySupplierOrCooperation(SimpleRequest simpleRequest){
        JSONObject jo = simpleRequest.getJO();
        List<Map> filters = simpleRequest.get("condition");
        JSONArray supplierIds = new JSONArray();
        JSONArray cooperation = new JSONArray();
        filters.forEach(item -> {
            switch ((String)item.get("field")){
                case "partner.id":
                    supplierIds.add(item.get("value"));
                    break;
                case "cooperation.id":
                    cooperation.add(item.get("value"));
                    break;
                    default:
                        break;
            }
        });
        JSONObject conditionModel = jo.getJSONObject("conditionModel");
        JSONObject belong = conditionModel.getJSONObject("belongDept");
        String belongDeptId = belong.getString("id");
        Dept belongDept = SpringManager.getBean(DeptRepository.class).findOne(belongDeptId);
//        String platformId ;
        String code ;
//        try {
//            platformId = jo.getJSONObject("conditionModel").getJSONObject("node").getJSONObject("platform").getString("id");
//            if(platformId == null || "".equals(platformId.trim())) throw new Exception("");
//        }catch (Exception e){
//            throw new RuntimeException("该单据有误，未获取到操作平台");
//        }
//        if("1001".equals(platformId)){
//            code = "supplier";
//        }else if("1007".equals(platformId)){
//            code = "platform";
//        }else{
//            throw new RuntimeException("该单据有误，未获取到操作平台");
//        }
//        List conditionList = new ArrayList();
//        conditionList.add("supplier");
//        conditionList.add("platform");
//        Group group = JpaDsl.getGroup(simpleRequest);
//        group.addFilters(
//                JpaDsl.toFilter(
//                        "validPeriod","GTE",   new Date(),
//                        "validFrom","LTE",   new Date(),
//                        "repealDate","EQ",   null,
//                        "approveDate","NE",   null,
//                        "contractType.code","IN",conditionList
//                )
//        );
        Sort sort = new Sort(Sort.Direction.ASC, "contractType.id");
        List<Contract> contractList = this.invoke("stock.replenishmentManagementService.getContract",
                MapUtil.mapper(
                        "companyId", belongDept.getCompany().getId(),
                        "supplierId", supplierIds
                ));
//        Page<Contract> page = contractRepository.findAll(group.build(false),PageRequest.of(simpleRequest.get("page"),simpleRequest.get("size"),sort));

        //过滤非带安的合同
        contractList = contractList.stream().filter(Contract::isConsignInstall).collect(Collectors.toList());

        if (!cooperation.isEmpty())contractList = contractList.stream().filter(contract -> contract.getCooperation().getId().equals(cooperation.getString(0))).collect(Collectors.toList());
        List listMap = contractList.stream().map((contract)->{
            Map map = MapUtil.mapped(contract);
            if(contract.getPartner().getParty().getCorporate().isWantInvoice()){
                map.put("wantInvoice","开票");
            }else{
                map.put("wantInvoice","不开票");
            }
            return map;
        }).collect(Collectors.toList());

        return pageInfo(jo ,listMap);
    }

    /**
     * 手动分页
     * @param jo
     * @param cross
     * @return
     */
    public PageImpl pageInfo(JSONObject jo, List cross){
        int size = (Integer) jo.get("page")*(Integer) jo.get("size");
        List result = new ArrayList<>();
        for (int i = size+1; i <= size+(Integer) jo.get("size"); i++) {
            if (cross.size()>=i)result.add(cross.get(i-1));
        }
        Pageable pageable = PageRequest.of(((Integer) jo.get("page")), (Integer) jo.get("size"));
        PageImpl page = new PageImpl(result, pageable, cross.size());
        return page;
    }
    /**
     * 公司入驻生成采购合同
     *
     * @param request
     * @return
     */
    @Listener(topic = "event:companyEntry.contract.approve")
    public void synCompanyContractApprove(SimpleRequest request) {
        Contract contract = request.getO(Contract.class);
//        if (contract.getCarryType() != null) {
//            if ("自提".equals(contract.getCarryType().getName())) {
//                List<SupplierShip> list = SpringManager.getBean(SupplierShipRepository.class).findAll(
//                        JpaDsl.toCriteriaByEq("supplier",contract.getPartner())
//                );
//                if (list.size() == 0) throw new RuntimeException("提货方式为自提的,要求供应商维护发货地点!!!");
//            } else if ("送货".equals(contract.getCarryType().getName())) {
//                List<SupplierReach> list = SpringManager.getBean(SupplierReachRepository.class).findAll(
//                        JpaDsl.toCriteriaByEq("supplier",contract.getPartner())
//                );
//                if (list.size() == 0) throw new RuntimeException("提货方式为送货的,要求供应商维护可送达仓库!!!");
//            }
//        }
        contract.setState("approve");
        contract.setApproveDate(new Date());
        contract.setApproveUid(this.getPerson(request));
        Contract result = contractRepository.saveAndFlush(contract);
        if(!switched){
            MQUtil.publish("mq.scmCghtService.insert", "公司入驻生成采购合同", MapUtil.mapped(result));
        }
    }

    /**
     * 推送采购审核至老系统
     *
     * @param request
     */
    @Consumer(topic = "mq.scmCghtService.insert")
    private void synUnifiedExport(SimpleRequest request) {
        Contract contract = request.getO(Contract.class);
        // 需将数据同步到老框架
        JSONObject returnCGHT = this.formatCGHT(contract);
        returnCGHT.put("CZY", contract.getCreator());
        piManager.synErp("scmCghtService.insert", returnCGHT);
    }

    /**
     * 销售流程（零售、）
     * 检查对应的合同，如果没有就创建一个对应的合同
     *
     * @param dept            部门
     * @param supplier        供应商
     * @param cooperationType 合作方式（经销、代销）
     * @param contractType    合同类型（采购合同、销售合同）
     * @return Contract
     */
    public Contract getContract(Dept dept, PartyRole supplier, String cooperationType, String contractType, String bizRemark) {
        // 获取运营模式
        String operation = dept.getCompany().getParty().getCorporate().getOperation().getId();

        // 判断是否为内部公司做采购（服务商品） 或者 A1001
        if ( (supplier.getId().equals(VoucherType.SUPPLIER_CODE) || "customer".equalsIgnoreCase(contractType) || supplier.getParty().getCorporate().inner())
            || !"001073".equals(operation)) {
            Contract contract = getContract(dept.getCompany().getId(), supplier.getId(), cooperationType, contractType);
            if (Objects.isNull(contract)) {
                contract = createContract(dept.getCompany(), supplier, dept, cooperationType, contractType, bizRemark);
            }
            return contract;
        } else {
            // 找平台合同
            Contract contract = getContract(VoucherType.PLATFORM_CODE, supplier.getId(), cooperationType, "platform");
            if (Objects.isNull(contract)) throw new RuntimeException(String.format("没有找到供应商 [ %s ] ，对应的[ %s ] 平台合同", supplier.getId(), VoucherType.PLATFORM_CODE));
            return contract;
        }
    }

    /**
     * 查询对应的合同
     *
     * @param companyId       公司编码
     * @param supplierId      供应商编码
     * @param cooperationType 合作方式
     * @param contractType    合同类型
     * @return Contract
     */
    public Contract getContract(String companyId, String supplierId, String cooperationType, String contractType) {
        List<Contract> contracts = contractRepository.findAllForSaleFlow(companyId, supplierId);
        Contract contract = contracts.stream()
                .filter(c -> cooperationType.equals(c.getCooperation().getId()) && contractType.equals(c.getContractType().getCode()))
                .findAny().orElse(null);
        return contract;
    }

    /**
     * 根据公司和供应商查询对应的合同
     *
     * @param companyId  公司编码
     * @param supplierId 供应商编码
     * @return List<Contract>
     */
    public List<Contract> getContract(String companyId, String supplierId) {
        return contractRepository.findAllForSaleFlow(companyId, supplierId);
    }

    /**
     * 创建采购合同
     * 在写入凭证时，没有找到合同，自动创建一个合同
     *
     * @param company         公司
     * @param partner         合作伙伴
     * @param dept            部门
     * @param cooperationType 合作方式
     * @param contractType    合同类型（customer, platform, supplier）
     * @return Contract
     */
    private Contract createContract(PartyRole company, PartyRole partner, Dept dept, String cooperationType, String contractType, String bizRemark) {
        Contract contract = new Contract();

        contract.setCompany(company);
        contract.setPartner(partner);
        contract.setDept(dept);
        contract.setState("approve");
        contract.setValidFrom(new Date());
        contract.setApproveDate(new Date());
        contract.setValidPeriod(DateUtil.add(new Date(), Calendar.YEAR, 10));
        contract.setSystemSource("2");
        contract.setState("delete");        // 状态特殊处理，不然会影响调拨账目

        // 合作方式
        Cooperation cooperation = SpringManager.getBean(CooperationRepository.class).findOne(cooperationType);
        contract.setCooperation(cooperation);
        contract.setName(partner.getParty().getAbbreviation() + cooperation.getName() + "合同");

        String ct = "";
        switch (contractType) {
            case "customer":
                ct = "Contract.contractType.customer";  // 销售合同
                break;
            case "platform":
                ct = "Contract.contractType.platform";  // 平台供应服务协议
                break;
            default:
                ct = "Contract.contractType.supplier";
        }

        contract.setMoveType(SpringManager.getBean(EnumerationRepository.class).findOne("one"));   // 交货方式
        contract.setContractType(SpringManager.getBean(BusinessAttributeValueRepository.class).findOne(ct));    // 合同类型
        contract.setSettlementType(SpringManager.getBean(EnumerationRepository.class).findOne("001421"));   // 账单
        contract = contractRepository.saveAndFlush(contract);       // 保存

        // 记录日志
        SpringManager.getBean(ApesLoggerService.class).sendSynEvent("event:ir.logger.create", MapUtil.mapper(
                "businessType", contract.getInnerBusinessType(),
                "businessKey", contract.getInnerBusinessKey(),
                "operate",  bizRemark +", 系统自动生成" ,
                "workPostName", null,
                "audit", null,
                "operator_id", 9326));  // 系统

        return contract;
    }

    public Object findContractNotInternalSupplier(SimpleRequest request) {
        JSONObject getJO = request.getJO();
        JSONArray filtersArray = getJO.getJSONObject("group").getJSONArray("filters");
        String id = "";
        for (int i = 0, iLen = filtersArray.size(); i < iLen; i++) {
            JSONObject filtersObj = filtersArray.getJSONObject(i);
            String field = filtersObj.getString("field");
            String value = filtersObj.getString("value");
            if ("id".equals(field)) {
                id = value;
            }
        }
        List<Contract> contractNotInternalSupplier = contractRepository.findContractNotInternalSupplier(id);
        Object paged = paged(contractNotInternalSupplier, request.get("page"), request.get("size"), null);
        return paged;
    }

    public void autoRepeal() {
        List<Contract> contracts = contractRepository.findAll(JpaDsl.toCriteria(
                "state","EQ","approve",
                "contractType.id","IN",Arrays.asList("Contract.contractType.supplier","Contract.contractType.platform"),
                "validPeriod","LT",new Date()
                ));

        contracts.forEach(contract -> {
            contract.setRepealUid(partyRoleRepository.findOne("system"));
            SimpleRequest request = new SimpleRequest();
            request.setData(contract);
            repeal(request);
            //写入日志
            apesLoggerService.sendSynEvent("event:ir.logger.create", MapUtil.mapper("businessType", "Contract",
                    "businessKey", contract.getId(), "operate", "终止", "operator_id", 1,"remark","超期自动终止"));
        });
    }
}
